package org.kth.dks.dks_dht;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.kth.dks.DKSObject;

public class DHTDiskStorage implements DHTStorage {
	private Logger log = Logger.getLogger(DHTDiskStorage.class);
	File basedir;
	String basedirname;
	
	public DHTDiskStorage(String bd){
		setBaseDir(bd);
	}
	
	void setBaseDir(String cd){
		basedirname=cd;
		basedir=new File(cd);
		
		if(!basedir.exists() || !basedir.isDirectory()){
			log.error( basedir+" is not a directory.");
			throw new NullPointerException();
		}
	}
	
	public void insertItem(long key, DKSObject value){
		String dirname=basedir+"/"+key;
		File dir=new File(dirname);
		if(!dir.exists()){
			dir.mkdir();
		}
		
		String[] filenames=dir.list();
		int count=filenames.length;
		String fn=dirname+"/"+count;
		File f=new File(fn);
		boolean cont=true;
		while(cont){
			try{
				if(!f.exists()){
					cont =false;
					f.createNewFile();
				}else{
					log.error("File existed");
					cont = true;
					count++;
					cont=true;
					fn=dirname+"/"+count;
					f=new File(fn);
				}
			}catch(IOException e){
				log.error("Caught io-exception!");
			}
		}
		try{
			FileOutputStream fos=new FileOutputStream(f);
			fos.write(value.getData());
		}catch(FileNotFoundException e){
			log.error("No such file!");
		}catch(IOException e){
			log.error("IO Exception!");
		}
		
		
	}
	
	public DKSObject[] lookupItem(long key){
		String dirname=basedir+"/"+key;
		File dir=new File(dirname);
		if(!dir.exists()){
			log.error("No such item."+dirname);
			return null;
		}
		
		String[] filenames=dir.list();
		int count=0;
		DKSObject[] result= new DKSObject[filenames.length];
		while(count < filenames.length){
			try{
				File f=new File(dirname+"/"+filenames[count]);
				if(!f.exists()){
					log.error("Fix me!"+filenames[count]);
					System.exit(-1);
				}else{
					FileInputStream fis=new FileInputStream(f);
					byte[] data=new byte[fis.available()];
					fis.read(data);
					result[count]=new DKSObject(data);
					fis.close();
				}
				count++;
			}catch(IOException e){
				log.error("Caught io-exception!\n"+e);
			}
		}
		return result;
	}
	
	
	public long[] getAllKeys(){
		long [] result;
		File dir=new File(basedirname);
		if(!dir.exists()){
			log.error("No basedir!"+basedirname); //FIXME!!!
			System.exit(-1);
		}
		
		String[] filenames=dir.list();
		int count=0;
		int pos=0;
		result= new long[filenames.length];
		while(count < filenames.length){
			try{
				count++;
				result[pos]=Long.parseLong(filenames[pos]);
				pos++;
			}catch(Exception e){
				log.error("Some kind of exception");
			}
		}
		return result;
	}
	
	
	
	public void removeItem(long key, DKSObject value){
		String dirname=basedir+"/"+key;
		File dir=new File(dirname);
		if(!dir.exists()){
			log.error("No such item."+dirname);
			return;
		}
		
		String[] filenames=dir.list();
		int count=0;
		while(count < filenames.length){
			try{
				File f=new File(dirname+"/"+filenames[count]);
				if(!f.exists()){
					log.error("Fix me!"+filenames[count]);
					System.exit(-1);
				}else{
					FileInputStream fis=new FileInputStream(f);
					byte[] data=new byte[fis.available()];
					fis.read(data);
					//FIXME: this is not an efficient way of comparing data.:)
					String s1=new String(data);
					String s2=new String(value.getData());
					if(s1.equals(s2)){
						log.error("Removing data!");
						f.delete();
						if(filenames.length==1)
							dir.delete();
					}
					fis.close();
				}
				count++;
			}catch(IOException e){
				log.error("Caught io-exception!\n"+e);
			}
		}
	}
	
	
	public void changeItem(long key, DKSObject oldvalue, DKSObject newvalue) {
	}
	
	public Iterator getEntriesIterator(){
		// Sorry, no idea of how to acomplish this, erik.
		return null;
	}
	
	
	public List     getAllItems(int r){
		return null; 
	}
}
